﻿using System;
using System.Collections.Generic;
using System.Text;
using Stone.Components;
using Stone.Services;
using System.Web;
using System.Threading;
using Stone.Services.EntityServices;
using Stone.Data;
using System.IO;

namespace Stone.Services
{
    public class Application
    {
        private static readonly string KEY_CONNECTION_SCOPE = typeof(ConnectionScope).Name;
        #region 单件模式
        private static Application instance;
        public static Application Instance
        {
            get { return instance; }
        }

        static Application()
        {
            instance = new Application();
        }
        #endregion

        public Application()
        {
            status = ApplicationStatus.Unstarted;
            appSettings = new AppSettings();
            //logService = new LogService(this);
            dataProviderManagerFactory = new DataProviderManagerFactory();

            dictEntityServices = new Dictionary<Type, DbServiceBase>();
        }

        public bool Start()
        {
            if (Status == ApplicationStatus.Starting ||
    Status == ApplicationStatus.Started) return true;
            if (Status == ApplicationStatus.Stopping)
            {
                HandleException(new ServiceException("应用程序正在停止,请稍候再启动!"));
                return false;
            }

            lock (SyncRoot)
            {
                if (Status == ApplicationStatus.Started) return true;

                status = ApplicationStatus.Starting;

                string currentStatus = "启动程序";
                try
                {
                    //currentStatus = "初始化日志记录";
                    //if (!String.IsNullOrEmpty(AppSettings.AppLogPath))
                    //{
                    //    try
                    //    {
                    //        //Logger.OpenLogFile(AppSettings.AppLogPath);
                    //    }
                    //    catch (Exception ex)
                    //    {
                    //        throw new ServiceException("无法在\"" + AppSettings.AppLogPath + "\"目录下创建日志文件!", ex);
                    //    }
                    //}

                    currentStatus = "初始化资源目录";
                    string resPath = AppSettings.GetResourcePath();
                    if (!String.IsNullOrEmpty(resPath))
                    {
                        if (!Directory.Exists(resPath))
                        {
                            try
                            {
                                Directory.CreateDirectory(resPath);
                            }
                            catch (Exception ex)
                            {
                                throw new ServiceException("无法创建资源目录\"" + resPath + "\"!", ex);
                            }
                        }
                    }

                    currentStatus = "初始化数据访问提供程序";

                    IDataProviderManager dataProviderManager = this.DataProviderManagerFactory[AppSettings.DbType];

                    if (dataProviderManager == null)
                    {
                        StringBuilder sb = new StringBuilder();
                        foreach (IDataProviderManager manager in this.DataProviderManagerFactory.GetAllManagers())
                        {
                            sb.Append(",").Append(manager.Key);
                        }
                        if (sb.Length > 0) sb.Remove(0, 1);
                        if (String.IsNullOrEmpty(AppSettings.DbType))
                        {
                            throw new ServiceException("初始化数据访问提供程序时,未指定数据提供程序[DB_TYPE为空]!(当前有效的DB_TYPE为:" + sb.ToString() + ")");
                        }
                        else
                        {
                            throw new ServiceException("初始化数据访问提供程序时,找不到类型为" + AppSettings.DbType + "的数据提供程序!(当前有效数据提供程序有:" + sb.ToString() + ")");
                        }
                    }

                    CurrentConnectionScope.DataProvider = dataProviderManager;
                    DataProviderManagerFactory.Default = dataProviderManager;

                    currentStatus = "设置数据访问提供程序参数";
                    dataProviderManager.SetDefaultConnectionString(
                        AppSettings.DbLocation,
                        AppSettings.DbPort,
                        AppSettings.DbName,
                        AppSettings.DbUser,
                        AppSettings.DbPassword);

                    currentStatus = "扫描所有数据实体服务并初始化";
                    dictEntityServices.Clear();
                    Type[] types = this.GetType().Assembly.GetTypes();
                    for (int i = 0; i < types.Length; i++)
                    {
                        if (!types[i].IsAbstract && typeof(DbServiceBase).IsAssignableFrom(types[i]))
                        {
                            DbServiceBase obj = Activator.CreateInstance(types[i], this) as DbServiceBase;
                            if (obj != null)
                            {
                                dictEntityServices.Add(types[i], obj);
                            }
                        }
                    }


                    currentStatus = "测试数据库连接";
                    DatabaseService dbService = dictEntityServices[typeof(DatabaseService)] as DatabaseService;
                    DateTime? dateTime = dbService.GetDataTime();

                    if (dateTime == null)
                    {
                        HandleException("测试数据库连接时失败!", dbService.LastException);
                        return false;
                    }



                    status = ApplicationStatus.Started;
                }
                catch (Exception ex)
                {
                    HandleException(currentStatus + "时失败!", ex);
                    status = ApplicationStatus.Unstarted;
                    return false;
                }
            }
            return true;
        }

        public bool Stop()
        {
            if (Status == ApplicationStatus.Unstarted ||
                Status == ApplicationStatus.Stopped ||
                Status == ApplicationStatus.Stopping) return true;

            if (Status == ApplicationStatus.Starting)
            {
                HandleException(new ServiceException("应用程序正在启动,请稍候再停止!"));
                return false;
            }

            lock (SyncRoot)
            {
                if (Status == ApplicationStatus.Stopped) return true;

                try
                {
                    //Logger.CloseLogFile();
                }
                catch { }
                lastException = null;
                status = ApplicationStatus.Stopped;
            }

            return true;
        }

        private readonly object syncRoot = new object();
        public object SyncRoot
        {
            get { return syncRoot; }
        }

        /// <summary>
        /// 最后一次异常
        /// </summary>
        protected Exception lastException;
        public Exception LastException
        {
            get { return lastException; }
        }

        protected virtual bool HandleException(string message, Exception ex)
        {
            lastException = new ServiceException(message, ex);
            //Logger.Error(message, ex);

            return false;
        }

        protected virtual bool HandleException(Exception ex)
        {
            lastException = ex;
            //Logger.Error("应用程序发生异常", ex);
            return false;
        }

        private ApplicationStatus status;
        public ApplicationStatus Status
        {
            get { return status; }
        }

        private AppSettings appSettings;
        public AppSettings AppSettings
        {
            get { return appSettings; }
        }

        //private LogService logService;
        //public LogService Logger
        //{
        //    get { return logService; }
        //}

        private DataProviderManagerFactory dataProviderManagerFactory;
        public DataProviderManagerFactory DataProviderManagerFactory
        {
            get { return dataProviderManagerFactory; }
        }

        public ConnectionScope CurrentConnectionScope
        {
            get
            {
                ConnectionScope scope = null;

                if (HttpContext.Current != null)
                {
                    scope = HttpContext.Current.Items[KEY_CONNECTION_SCOPE] as ConnectionScope;

                    if (scope == null)
                    {
                        scope = new ConnectionScope(this);
                        HttpContext.Current.Items[KEY_CONNECTION_SCOPE] = scope;
                    }
                }
                else
                {
                    LocalDataStoreSlot slot = Thread.GetNamedDataSlot(KEY_CONNECTION_SCOPE);
                    scope = Thread.GetData(slot) as ConnectionScope;

                    if (scope == null)
                    {
                        scope = new ConnectionScope(this);
                        Thread.SetData(slot, scope);
                    }
                }

                return scope;
            }
        }

        private Dictionary<Type, DbServiceBase> dictEntityServices;
        public T GetDbService<T>()
            where T : DbServiceBase
        {
            if (Status != ApplicationStatus.Started) throw new ServiceException("应用程序尚未启动,不能获得实体服务!");
            lock (SyncRoot)
            {
                return dictEntityServices[typeof(T)] as T;
            }
        }
    }

    public enum ApplicationStatus
    {
        Unstarted,
        Starting,
        Started,
        Stopping,
        Stopped,
    }
}
